import 'dart:convert';

import 'package:crypto/crypto.dart';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';

import 'api_response.dart';
import 'app_exceptions.dart';

class Request<T> {
  Request(this.dio, this.path, {this.params, this.options, this.curstomHandleResponseCallback});

  Dio dio;
  String path;
  Map<String, dynamic>? params;
  Options? options;
  Function? curstomHandleResponseCallback;

  String get _cacheKey => _getCacheKey();


  Future<ApiResponse<T>> get({bool inCache = false}) async {
    try {
      var response = await dio.get(path, queryParameters: params, options: options);
      ApiResponse<T> apiResponse = _handleResponse(response);
      if (apiResponse.isOk() && (inCache)) {
      }
      return apiResponse;
    } catch (e) {
      return _handleError(e);
    }
  }

  Future<ApiResponse<T>> post({bool inCache = false}) async {
    try {
      var response = await dio.post(path, data: params, options: options);
      ApiResponse<T> apiResponse;
      if (curstomHandleResponseCallback != null) {
        apiResponse = curstomHandleResponseCallback!(response);
      } else {
        apiResponse = _handleResponse(response);
      }
      if (apiResponse.isOk() && (inCache)) {
      }
      return apiResponse;
    } catch (e) {
      return _handleError(e);
    }
  }

  String _getCacheKey() {
    String urlKey = "$path${params.toString()}";
    var content = const Utf8Encoder().convert(urlKey);
    String cacheKey = md5.convert(content).toString();
    return cacheKey;
  }

  ApiResponse<T> _handleResponse(Response response) {
    debugPrint("statusCode:${response.statusCode}--statusMessage:${response.statusMessage}");
    if (response.statusCode == 200) {
      dynamic json;
      if (response.data is Map<String, dynamic> || response.data is List<dynamic>) {
        json = response.data;
      } else {
        json = jsonDecode(response.data);
      }
      try {
        ApiResponse<T> apiResponse = ApiResponse.completed(json, response.statusCode);
        return apiResponse;
      } catch (e) {
        return ApiResponse.error(AppException.create(e));
      }
    } else {
      return ApiResponse.error(AppException.errResponse(response));
    }
  }

  Future<ApiResponse<T>> _handleError(dynamic e) async {
      return ApiResponse.error(AppException.create(e is DioError ? e.error : e));
  }
}
